﻿#include "CEngine.h"
using namespace Util;

using namespace Engine;

CEngine* CEngine::pInstance = 0;

CEngine::CEngine(HINSTANCE hInst, HINSTANCE hPrevInst, wchar_t * lpCmdLine, int nCmdShow,WNDPROC MsgProc,const char * windowName,const char * title):hInst(hInst),hPrevInst(hPrevInst),lpCmdLine(lpCmdLine),nCmdShow(nCmdShow),windowName(windowName),title(title)
{
	if (!createWindow(MsgProc))
   {
     LOG_ERROR("Nem sikerult az ablakot letrehozni. Kilepes.")
     exit(1);
   }
  // eszköz itt lesz létrehozva
	pDevice=CDevice::createDevice(hWnd);

  // az input itt lesz létrehozva
  pInput = CInput::getInstance();

  // input inicializálása
  pInput->init(hInst,hWnd);

  // renderer is itt lesz létrehozva
	pRenderer=CRenderer::getInstance();
  pResourceManager = pResourceManager->getInstance();
  pRenderer->setPrimitiveQueue(pResourceManager->getPrimitives());
  pRenderer->setMeshQueue(pResourceManager->getMeshes());
  pRenderer->setGUIQueue(pResourceManager->getGUIObjects());

  pTimer = CTimer::getTimerInstance();
}

CEngine::~CEngine()
{
  pTimer = 0;
  CTimer::destroy();
  pRenderer = 0;
  CRenderer::destroy();
  pInput = 0;
  CInput::destroy();
  pDevice = 0;
  CDevice::destroy();
  pResourceManager = 0;
  Content::CResourceManager::destroy();
  CErrorLogger::destroy();
  
}

bool CEngine::createWindow(WNDPROC MsgProc)
{
	bool ret = true;

	UNREFERENCED_PARAMETER( hInst );
	
	
	// registerWindowClass
	WNDCLASSEX wc =
	{
		sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
		GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
		windowName, NULL
	};
	RegisterClassEx( &wc );
	int screenWidth=GetSystemMetrics(SM_CXSCREEN);
	int screenHeight=GetSystemMetrics(SM_CYSCREEN);
	 // ablak létrehozása
	hWnd =  CreateWindow( windowName, title,
						   WS_EX_TOPMOST | WS_POPUP, 0, 0, screenWidth, screenHeight,
						  NULL, NULL, wc.hInstance, NULL );
  if (NULL == hWnd)
  {
    ret = false;
  }
	hInstance=wc.hInstance;

	return ret;
}

IEngine* CEngine::getInstance(HINSTANCE hInst, HINSTANCE hPrevInst, wchar_t * lpCmdLine, int nCmdShow,WNDPROC MsgProc,const char * windowName,const char * title)
{
	if (0 == pInstance)
	{
		pInstance = new CEngine(hInst, hPrevInst, lpCmdLine, nCmdShow,MsgProc,windowName,title);
	}
	return pInstance;
}

HWND CEngine::getWindowIdentifier()
{
	return hWnd;
}

void CEngine::update()
{
  pInput->detectInput();
 	pTimer->update();

//  Sleep(500);
  // alt+enterre váltás teljes képernyős és ablakos mód között
  if (pInput->isKeyDown(DIK_LALT) && pInput->isKeyPressed(DIK_RETURN))
  {
    pDevice->switchScreenMode();
    pRenderer->updateMatProj();
  	// IDirect3DDevice9::Reset() elõtt fel kell szabadítani a 
  	// videomemóriában lefoglalt erõforrásokat

  	pRenderer->onLostDevice();

  	// Állísuk vissza az elveszett eszközt: erre a célra kizárólag 
	  // a Reset() hívás alkalmazható.
    HRESULT hr= pDevice->resetDevice();

  	// A Reset() mindaddig hibával tér vissza, míg nem szabadítjuk fel
  	// az összes D3DPOOL_DEFAULT memóriaosztályba tartozó erõforrást,
  	// beleértve az IDirect3DDevice9::CreateRenderTarget() és 
  	// IDirect3DDevice9::CreateDepthStencilSurface() hívásokkal létrehozottakat.
  	if( FAILED( hr ) )
  	{
  		const wchar_t errorStr[] = L"Hiba az eszköz újrainicializálásakor.";
  		::MessageBoxW(0, errorStr, 0, 0);		
  	}

	  // Sikeresen helyreállítottuk eszközünket, úgyhogy újra le kell foglalnunk
	  // a Reset() hívást megelõzõen felszabadított erõforrásokat
	  pRenderer->onResetDevice();
  }
}

void CEngine::render()
{
	pRenderer->render();
}

void CEngine::cleanUp()
{
	//Device felszabadítása
	pRenderer->clean();
	pDevice->clean();

  pResourceManager->clean();
	//renedrer felszabadítása
	UnregisterClass( this->windowName, hInstance);
}

void CEngine::setCamera(ICamera* pCam)
{
  pRenderer->setCamera(reinterpret_cast<Content::CCamera*>(pCam));
}


int CEngine::getScreenWidth()
{
  return pDevice->getScreenWidth();
}

int CEngine::getScreenHeight()
{
  return pDevice->getScreenHeight();

}

void CEngine::setSkyBoxTexture(std::string texture_in)
{
  if (pRenderer)
  {
    pRenderer->setSkyBoxTexture(texture_in);
  }
}


